[AWS Step Functions / AWS CDK] 任意のJavaScript表現を実行できるEvaluateExpressionタスクを使って文字列置換をしてみた
こんにちは、CX事業本部 IoT事業部の若槻です。
今日もいつものようにAWS Step Fucntionsのドキュメントやソースコードを見ていたところ、EvaluateExpressionなるものを見つけました。
内容を見てみると、なんと任意のJavaScript表現を実行できるタスクのようです...!!!
そこで今回は、EvaluateExpressionタスクを使って文字列置換を行うステートマシンを実装してみました。
やってみた
実装
AWS CDK v2(TypeScript)で次のようなCDKスタックを作成します。
import { Construct } from 'constructs'; import { aws_stepfunctions, aws_stepfunctions_tasks, Stack, StackProps, } from 'aws-cdk-lib'; export class ProcessStack extends Stack { constructor(scope: Construct, id: string, props: StackProps) { super(scope, id, props); //JSONPathを使わない場合 const evaluateTask1 = new aws_stepfunctions_tasks.EvaluateExpression( this, 'evaluateTask1', { expression: '"インスタンスメソッド".replace("インスタンス", "クラス")', resultPath: '$.evaluateTask1', }, ); //JSONPathを使う場合 const evaluateTask2 = new aws_stepfunctions_tasks.EvaluateExpression( this, 'evaluateTask2', { expression: aws_stepfunctions.JsonPath.format( '"{}".replace("{}", "{}")', aws_stepfunctions.JsonPath.stringAt('$.original'), aws_stepfunctions.JsonPath.stringAt('$.substr'), aws_stepfunctions.JsonPath.stringAt('$.newSubstr'), ), resultPath: '$.evaluateTask2', }, ); // ステートマシン new aws_stepfunctions.StateMachine(this, 'stateMachine', { stateMachineName: 'stateMachine', definition: evaluateTask1.next(evaluateTask2), }); } }
EvaluateExpression()
のexpression
で、実行したいJavaScript表現を指定します。States.Format
を使用してInputの値を指定すること可能です。
上記をCDK Deployしてスタックをデプロイします。これにより次のDefinitionのステートマシンが作成されます。種明かしなのですがEvaluateExpression()
はLambda関数リソース(Node.jsランタイム)が隠蔽されたHigh Level Constructです。
{ "StartAt": "evaluateTask1", "States": { "evaluateTask1": { "Next": "evaluateTask2", "Type": "Task", "ResultPath": "$.evaluateTask1", "Resource": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:ProcessStack-Evalda2d1181604e4a4586941a6abd7fe42dF-oEnIyas250LB", "Parameters": { "expression": "\"インスタンスメソッド\".replace(\"インスタンス\", \"クラス\")", "expressionAttributeValues": {} } }, "evaluateTask2": { "End": true, "Type": "Task", "ResultPath": "$.evaluateTask2", "Resource": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:ProcessStack-Evalda2d1181604e4a4586941a6abd7fe42dF-oEnIyas250LB", "Parameters": { "expression.$": "States.Format('\"{}\".replace(\"{}\", \"{}\")', $.original, $.substr, $.newSubstr)", "expressionAttributeValues": {} } } } }
作成されたLambda関数のコードを見ると、引数のexpression
をeval()
してReturnしていることが分かります。
'use strict'; Object.defineProperty(exports, '__esModule', { value: !0 }), (exports.handler = void 0); function escapeRegex(x) { return x.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); } async function handler(event) { console.log('Event: %j', event); const expression = Object.entries(event.expressionAttributeValues).reduce( (exp, [k, v]) => exp.replace(new RegExp(escapeRegex(k), 'g'), JSON.stringify(v)), event.expression ); return console.log(`Expression: ${expression}`), eval(expression); } exports.handler = handler; //# sourceMappingURL=index.js.map
動作確認
次の入力を指定してステートマシンを実行します。
{ "original": "オールドモード", "substr": "オールド", "newSubstr": "ネクスト" }
実行が成功しました。
evaluateTask1
では、文字列置換によりクラスメソッド
が取得できています!
evaluateTask1
では、JSONPathの入力を元にした文字列置換によりネクストモード
が取得できています!
おわりに
任意のJavaScript表現を実行できるEvaluateExpressionタスクを使って文字列置換をしてみました。
ある程度の処理のタスクであれば最小限のコードの記述だけで作成できてしまうなんて凄すぎますね。今回やった文字列置換の他にも四則演算や日付処理などeval()
に渡せるものなら何でも出来てしまいます。
ローコードツールとしてのAWS Step Functionsの可能性を大幅に拡張する機能だと思うので、今後はどんどん利用し、またどんどん周知していきたいと思います。
参考
以上